package middleware

import (
	constant "back/constant"
	"github.com/golang-jwt/jwt/v5"
	"time"
)

type UserClaims[T any] struct {
	*jwt.RegisteredClaims
	Data T `json:"data"`
}

func CreatJwtTokenWithClaims[T any](uc UserClaims[T]) (string, error) {
	nowTime := time.Now()
	uc.RegisteredClaims = &jwt.RegisteredClaims{
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(constant.Config.JWTConfig.Duration())),
		Issuer:    constant.JWTIssuer,              // 签发人
		IssuedAt:  &jwt.NumericDate{Time: nowTime}, //签发时间
	}
	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, uc)
	// 使用指定的secret签名,获取字符串token
	tokenStr, err := claims.SignedString([]byte(constant.Config.JWTConfig.SigningKey))
	if err != nil {
		return "", err
	}
	return tokenStr, nil
}
func ParseWithClaims[T any](tokenString string) (UserClaims[T], error) {
	var nilClaim UserClaims[T]
	// 如果令牌无效（如果令牌已根据我们设置的登录到期时间过期）或者签名不匹配,此方法会返回错误.
	if token, err := jwt.ParseWithClaims(tokenString, &nilClaim, func(token *jwt.Token) (any, error) {
		return []byte(constant.Config.JWTConfig.SigningKey), nil
	}); err != nil {
		return nilClaim, err
	} else {
		if token == nil {
			return nilClaim, constant.ErrTokenParse
		}
		if claims, ok := token.Claims.(*UserClaims[T]); ok && token.Valid {
			return *claims, nil
		}
	}
	return nilClaim, constant.ErrTokenParse
}
